﻿// <copyright file="Man.cs" company="ALCPU">
// Copyright (c) 2010 All Right Reserved
// </copyright>
// <author>Arthur Liberman</author>
// <email>Arthur_Liberman@hotmail.com</email>
// <date>04-07-2010</date>
// <summary>Contains Checks Man definition.</summary>

namespace Chess.Checkers
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Media;
    using Chess.Figures;
    using ChessDefinitions;

    /// <summary>
    /// The left/right direction of the piece.
    /// </summary>
    public enum CheckersPieceDirection
    {
        /// <summary>
        /// The left-up direction.
        /// </summary>
        LeftUp,

        /// <summary>
        /// The right-up direction.
        /// </summary>
        RightUp,

        /// <summary>
        /// The left-down direction.
        /// </summary>
        LeftDown,

        /// <summary>
        /// The right-down direction.
        /// </summary>
        RightDown
    }

    /// <summary>
    /// Representative of the Man piece
    /// </summary>
    public class Man : CheckersPiece
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="Man"/> class.
        /// </summary>
        /// <param name="color">The piece color.</param>
        /// <param name="gameboard">The gameboard.</param>
        /// <param name="position">The starting position.</param>
        public Man(IPieceColor color, Gameboard gameboard, Position position)
            : base(color, gameboard, position)
        {
            this.SetImage(color);
            this.Gameboard.MovePiece(position, this);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Man"/> class.
        /// </summary>
        /// <param name="piece">The piece.</param>
        public Man(IPiece piece)
            : base(piece)
        {
            this.SetImage(this.Color);
            this.Gameboard.MovePiece(this.Position, this);
        }

        /// <summary>
        /// Prevents a default instance of the <see cref="Man"/> class from being created.
        /// </summary>
        private Man()
            : base(0, null, new Position())
        {
        }

        #region IFigure Members

        /// <summary>
        /// Attacks the specified target.
        /// </summary>
        /// <param name="target">The target.</param>
        /// <returns>
        ///     <c>true</c> if successful, <c>false</c> if not.
        /// </returns>
        public override bool Attack(Position target)
        {
            bool ret = false;

            if (this.AttackOptions.Contains(target))
            {
                this.Gameboard.Figures[target].Die(this);
                target = (2 * (target - this.Position)) + this.Position;
                ret = this.MoveTo(target, true);
            }

            return ret;
        }

        /// <summary>
        /// Dies by the specified attacker.
        /// </summary>
        /// <param name="attacker">The attacker.</param>
        public override void Die(IPiece attacker)
        {
            base.Die(attacker);
            this.Gameboard.ClearSquare(this.Position);
        }

        #endregion

        /// <summary>
        /// Moves the piece to the destination.
        /// </summary>
        /// <param name="destination">The destination.</param>
        /// <param name="ignoreMoveOptions">if set to <c>true</c> ignores move options.</param>
        /// <returns>
        ///     <c>true</c> if successful, <c>false</c> if not.
        /// </returns>
        protected override bool MoveTo(Position destination, bool ignoreMoveOptions)
        {
            bool ret = base.MoveTo(destination, ignoreMoveOptions);

            if (ret)
            {
                if ((this.Color == IPieceColor.White && destination.Y == 0) || 
                    (this.Color == IPieceColor.Black && destination.Y == 7))
                {
                    this.NotifyOfGameEvent(this, GameEventType.Crowned);
                }
            }

            return ret;
        }

        /// <summary>
        /// Fills the move options.
        /// </summary>
        /// <returns>List of moves.</returns>
        protected override List<Position> GetMoveOptions()
        {
            List<Position> posList = new List<Position>();

            if (this.Color == IPieceColor.White)
            {
                if (this.Gameboard.IsSquareFree(this.Position + new Position(1, -1)))
                {
                    posList.Add(this.Position + new Position(1, -1));
                }

                if (this.Gameboard.IsSquareFree(this.Position + new Position(-1, -1)))
                {
                    posList.Add(this.Position + new Position(-1, -1));
                }
            }
            else
            {
                if (this.Gameboard.IsSquareFree(this.Position + new Position(1, 1)))
                {
                    posList.Add(this.Position + new Position(1, 1));
                }

                if (this.Gameboard.IsSquareFree(this.Position + new Position(-1, 1)))
                {
                    posList.Add(this.Position + new Position(-1, 1));
                }
            }

            return posList;
        }

        /// <summary>
        /// Fills the attack list.
        /// </summary>
        /// <returns>List of possible attacks.</returns>
        protected override List<Position> GetAttackList()
        {
            List<Position> posList = new List<Position>();

            if (this.Color == IPieceColor.White)
            {
                if (this.IsSquareAttackable(CheckersPieceDirection.RightUp))
                {
                    posList.Add(this.Position + new Position(1, -1));
                }

                if (this.IsSquareAttackable(CheckersPieceDirection.LeftUp))
                {
                    posList.Add(this.Position + new Position(-1, -1));
                }
            }
            else
            {
                if (this.IsSquareAttackable(CheckersPieceDirection.RightDown))
                {
                    posList.Add(this.Position + new Position(1, 1));
                }

                if (this.IsSquareAttackable(CheckersPieceDirection.LeftDown))
                {
                    posList.Add(this.Position + new Position(-1, 1));
                }
            }

            return posList;
        }

        /// <summary>
        /// Determines whether the square is attackable in the specified direction.
        /// </summary>
        /// <param name="direction">The direction.</param>
        /// <returns>
        ///     <c>true</c> if the square is attackable in the specified direction; otherwise, <c>false</c>.
        /// </returns>
        protected bool IsSquareAttackable(CheckersPieceDirection direction)
        {
            bool ret = false;

            switch (direction)
            {
                case CheckersPieceDirection.LeftDown:
                    ret = this.Gameboard.IsSquareFree(this.Position + new Position(-2, 2)) &
                        this.Gameboard.IsSquareAttackable(this.Position + new Position(-1, 1), this);
                    break;
                case CheckersPieceDirection.LeftUp:
                    ret = this.Gameboard.IsSquareFree(this.Position + new Position(-2, -2)) &
                        this.Gameboard.IsSquareAttackable(this.Position + new Position(-1, -1), this);
                    break;
                case CheckersPieceDirection.RightDown:
                    ret = this.Gameboard.IsSquareFree(this.Position + new Position(2, 2)) &
                        this.Gameboard.IsSquareAttackable(this.Position + new Position(1, 1), this);
                    break;
                case CheckersPieceDirection.RightUp:
                    ret = this.Gameboard.IsSquareFree(this.Position + new Position(2, -2)) &
                        this.Gameboard.IsSquareAttackable(this.Position + new Position(1, -1), this);
                    break;
            }

            return ret;
        }

        /// <summary>
        /// Sets the image.
        /// </summary>
        /// <param name="color">The color.</param>
        private void SetImage(IPieceColor color)
        {
            if (color == IPieceColor.Black)
            {
                this.Image = (Brush)App.Current.FindResource("BlackDraughtsMan");
            }
            else if (color == IPieceColor.White)
            {
                this.Image = (Brush)App.Current.FindResource("WhiteDraughtsMan");
            }
        }
    }
}
